#include "page.h"
#include "download_manager.h"
//#include "db_operate.h"
//#include "db_manager.h"
#include "schema_manager.h"
#include "parse.h"
#include "log.h"




download_manager_t g_download_manager;

memory_block* create_memory_block()
{
	struct memory_block* m =new memory_block;
	m->pblock = NULL;
	m->len = 0;
	return m;	
}

void delete_memory_block(memory_block* m)
{
	if( m == NULL)	
		return;
	if(m->pblock)
		free(m->pblock);
	delete m;
	m = NULL;
}

void* memory_apply(void* p, size_t len)
{
	if(p)
		return realloc(p, len);
	else
		return malloc(len);
}
size_t memory_write(void* raw_data, size_t len,
                    size_t num, void* pmemory)
{
	size_t all_len = len * num;
	struct memory_block* pmb = (struct memory_block*)pmemory;
	pmb->pblock = (unsigned char*)memory_apply(pmb->pblock, pmb->len +  all_len + 1);
	if( pmb->pblock)
	{
		memcpy(&(pmb->pblock[pmb->len]), raw_data, all_len);
		pmb->len += all_len;
		pmb->pblock[pmb->len] = 0;
	}
	return all_len;
}

void quit_pthread_download(list<url_t*>& urls,
		pthread_mutex_t& locker,pthread_cond_t&  cond )
{
	//nothing now
	list<url_t*>::iterator it = urls.begin();
	for(; it != urls.end(); it++)
	{
		release_url((void*)(*it));
	}
	urls.clear();
	pthread_mutex_destroy(&locker);
	pthread_cond_destroy(&cond);
}

bool is_valid_url(url_t* purl_t, memory_block* m)
{
	if( purl_t == NULL || m == NULL || m->pblock == 0 || m->len == 0)
		return false;
	return true;	
}

	

void* pthread_download(void* data)
{
//	if( data == NULL) 	return 0;  //index from 0 to DOWNLOAD_THREADS_COUNT
	pthread_detach(pthread_self());
	
	int i = (int)data;
	list<url_t*>& urls = g_download_manager.urls[i];
	list<url_t*>::iterator it;
	
	pthread_mutex_t& locker = g_download_manager.lockers[i];;
	pthread_cond_t&  cond = g_download_manager.conds[i];
	
	while(!g_download_manager.quit)
	{
		pthread_mutex_lock(&locker);
		while(urls.size()==0)
		{
			pthread_cond_wait(&cond, &locker);
		}
		url_t* purl_t = urls.front();
		urls.pop_front();
		pthread_mutex_unlock(&locker);
		
		if( purl_t == 0)
			continue;
		
		printf("download_manager: %d for %s\n", i, purl_t->szurl);	
		logger("download_manager: %d for %s\n", i, purl_t->szurl);
		
		struct memory_block* m = create_memory_block();
	
		CURL* curl = curl_easy_init();
		curl_easy_setopt(curl, CURLOPT_URL, purl_t->szurl);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memory_write);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)m);
		curl_easy_setopt(curl, CURLOPT_USERAGENT, "liburl-agent/1.0");
		curl_easy_perform(curl);
		curl_easy_cleanup(curl);
	
		if(is_valid_url(purl_t, m))
		{
			parse(purl_t, m);
			release_url((void*) purl_t );
		}
		else
		{
		//	increase_url(purl_t,2);
			//add_url_to_invalid(purl_t, &g_db_manager);
			//remove_url_from_pending(purl_t, &g_db_manager);
			remove_invalid_url(purl_t);
			release_url((void*) purl_t );
		}
		delete_memory_block(m);
	}
	quit_pthread_download(urls,locker,cond);
	return 0;
}


int init_download_manager(download_manager_t& download_manager)
{
	download_manager.quit = false;
	for(int i = 0; i < DOWNLOAD_THREADS_COUNT; i++)
	{
		pthread_mutex_init(&download_manager.lockers[i], NULL);
	}
	for(int i = 0; i < DOWNLOAD_THREADS_COUNT; i++)
	{
		pthread_cond_init(&download_manager.conds[i], NULL);
	}
	
	pthread_t th_download_manager[DOWNLOAD_THREADS_COUNT];
	for(int i = 0 ; i < DOWNLOAD_THREADS_COUNT; i++)
	{
		pthread_create(&th_download_manager[i], NULL, &pthread_download,
					   (void*)i);
	}
	return 0;
	
}

int add_url_to_download_manager(url_t* url, download_manager_t* download_manager)
{
	if( url == 0 || download_manager == 0)
		return -1;

	static  int index = 0;
	index++;
	if(index >= DOWNLOAD_THREADS_COUNT)
		index = 0;
		
	pthread_mutex_lock(&download_manager->lockers[index]);
	download_manager->urls[index].push_back(url);
	pthread_cond_signal(&download_manager->conds[index]);
	pthread_mutex_unlock(&download_manager->lockers[index]);
	return 0;
}
int add_urls_to_download_manager(list<url_t*>& urls, download_manager_t* download_manager)
{
	if( urls.size() == 0 || download_manager == 0)
		return -1;
		
	int index = 0;	
	list<url_t*>::iterator it = urls.begin();
	for(; it != urls.end(); it++)
	{
		index++;
		if(index >= DOWNLOAD_THREADS_COUNT)
			index = 0;
		pthread_mutex_lock(&download_manager->lockers[index]);
		download_manager->urls[index].push_back((*it));
		pthread_cond_signal(&download_manager->conds[index]);
		pthread_mutex_unlock(&download_manager->lockers[index]);
	}	
	return 0;
}

void quit_download_manager(download_manager_t* download_manager)
{
	download_manager->quit = true;
}

